# This file is part of the open-lmake distribution (git@github.com:cesar-douady/open-lmake.git)
# Copyright (c) 2023-2026 Doliam
# This program is free software: you can redistribute/modify under the terms of the GPL-v3 (https://www.gnu.org/licenses/gpl-3.0.html).
# This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

import os

import lmake

if __name__!='__main__' :

    from step import rustup_home
    os.environ['RUSTUP_HOME'] = rustup_home # set before importing lmake.rules so RustRule is correctly configured

    from lmake.rules import Rule,HomelessRule,RustRule

    from step import step,has_jemalloc

    lmake.manifest = (
        'Lmakefile.py'
    ,   'step.py'
    ,   'hello/Cargo.toml'
    ,   'hello/src/main.rs'
    ,   'hello.in'
    ,   'hello.ref'
    )

    class CompileRust(HomelessRule,RustRule) :
        targets      = { 'EXE'        :   r'{Dir:.+/|}{Module:[^/]+}/target/debug/{Module}'                   }
        side_targets = { 'SCRATCHPAD' : ( r'{Dir     }{Module      }/{*:.*}'                , 'Incremental' ) }
        deps = {
            'PKG' : '{Dir}{Module}/Cargo.toml'
        ,   'SRC' : '{Dir}{Module}/src/main.rs'
        }
        if   step==1      : autodep = 'ld_preload_jemalloc'
        elif step==2      : autodep = 'ptrace'
        if   has_jemalloc : environ = { 'LD_PRELOAD' : 'libjemalloc.so' }
        stderr_ok = True
        cmd       = 'cd {Dir}{Module} ; cargo build'

    class RunRust(RustRule) :
        targets = { 'OUT' : r'{Dir:.+/|}{Module:[^/]+}.out'                   }
        deps    = { 'EXE' : r'{Dir     }{Module      }/target/debug/{Module}' }
        cmd     = './{EXE}'

    class Cmp(Rule) :
        target = r'{File:.*}.ok'
        deps   = {
            'OUT' : '{File}.out'
        ,   'REF' : '{File}.ref'
        }
        cmd = 'diff {REF} {OUT}'

else :

    import os.path as osp
    import shutil
    import subprocess as sp
    import sys

    import ut

    cargo = shutil.which('cargo')
    if not cargo :
        print('cargo not available',file=open('skipped','w'))
        exit()

    rustup_home = osp.dirname(osp.dirname(osp.dirname(cargo)))+'/.rustup'
    print(f'rustup_home={rustup_home!r}',file=open('step.py','w'))

    sav = os.environ.get('LD_PRELOAD')
    os.environ['LD_PRELOAD'] = 'libjemalloc.so'
    has_jemalloc             = not sp.run(('/usr/bin/echo',),check=True,stderr=sp.PIPE).stderr
    if sav is None : del os.environ['LD_PRELOAD']
    else           :     os.environ['LD_PRELOAD'] = sav
    print(f'has_jemalloc={has_jemalloc}',file=open('step.py','a'))

    os.makedirs('hello/src',exist_ok=True)
    toml = open('hello/Cargo.toml','w')
    print(
        '[package]'
    ,   'name    = "hello"'
    ,   'version = "0.1.0"'
    ,   'edition = "2021"'
    ,   sep  = '\n'
    ,   file = open('hello/Cargo.toml','w')
    )
    print('''
        use std::fs::File       ;
        use std::io::prelude::* ;

        fn main() -> std::io::Result<()> {
            let mut file     = File::open("hello.in")? ;
            let mut contents = String::new()           ;
            file.read_to_string(&mut contents)?        ;

            let mut file = File::create("hello.out")? ;
            file.write_all(b"hello world\n")?         ;

            return Ok(()) ;
        }
    ''',file=open('hello/src/main.rs','w'))
    print('hello world',file=open('hello.in' ,'w'))
    print('hello world',file=open('hello.ref','w'))

    print(f'step=1',file=open('step.py','a'))
    ut.lmake( 'hello.ok' , done=3 , new=4 )

    print(file=open('hello/src/main.rs','a'))
    ut.lmake( 'hello.ok' , steady=1 , changed=1 ) # check cargo can run twice with no problem

    if 'ptrace' in lmake.autodeps :
        print(f'step=2',file=open('step.py','a'))
        os.system('rm -rf hello/target hello.ok') # force cargo to regenerate everything
        ut.lmake( 'hello.ok' , steady=1 )         # check ptrace works with cargo