Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is the best way to use vcvars? #347

Open
doctorpangloss opened this issue Jul 26, 2023 · 11 comments
Open

What is the best way to use vcvars? #347

doctorpangloss opened this issue Jul 26, 2023 · 11 comments

Comments

@doctorpangloss
Copy link

Since the busybox environment isn't mingw, it is suitable for native build tools as though it were cmd but a better shell.

Any opinions how to use the scripts with busybox?

@garoto
Copy link

garoto commented Jul 26, 2023

say again?

@doctorpangloss
Copy link
Author

lots of build tooling expects environment variables set using vcvars*.bat a set of utilities from the Visual Studio toolchain:

https://learn.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-170

My question is how to do this in the context of the busybox shell.

@rmyorston
Copy link
Owner

rmyorston commented Jul 27, 2023

To run a shell in the context created by running a batch file you could do something like:

~ $ cmd /k "whatever.bat & busybox sh & exit"

Or more concisely:

~ $ cmd /c "whatever.bat & busybox sh"

@doctorpangloss
Copy link
Author

for future reference:

cmd /c 'C:\PROGRA~2\MICROS~2\2022\BUILDT~1\VC\AUXILI~1\Build\VCVARS~1.BAT amd64 & busybox sh -ilX'

@doctorpangloss doctorpangloss reopened this Aug 9, 2024
@doctorpangloss
Copy link
Author

How would I do this in a .profile? @rmyorston

@ale5000-git
Copy link

ale5000-git commented Aug 9, 2024

The .profile file is a shell script, just put the shell code inside it.
Inside the .profile you could just put:
'C:\PROGRA~2\MICROS~2\2022\BUILDT~1\VC\AUXILI~1\Build\VCVARS~1.BAT' amd64
PS: I suggest to use the long name, not the dos name.

Then when executing busybox ash -l it automatically execute the .profile file.

@doctorpangloss
Copy link
Author

the side effects of the vcvars script are not applied to the currently running shell

here was what I ultimately added:

temp_file=$(mktemp)

cmd /c 'C:\PROGRA~2\MICROS~2\2022\BUILDT~1\VC\AUXILI~1\Build\VCVARS~1.BAT amd64 && set' | 
sed '1,5d' | 
while IFS= read -r line
do

    line=${line%$'\r'}
    

    [ -z "$line" ] && continue
    

    key=${line%%=*}
    value=${line#*=}
    

    case "$key" in
        *[!a-zA-Z0-9_]*) continue ;;
    esac
    

    value=$(echo "$value" | sed 's/[\\()$`]/\\&/g')
    

    echo "export $key=\"$value\"" >> "$temp_file"
done

echo "export CC=cl" >> "$temp_file"
echo "export CXX=cl" >> "$temp_file"

. "$temp_file"

rm "$temp_file"

@ale5000-git
Copy link

ale5000-git commented Aug 9, 2024

It is difficult because I don't have a vcvars file at hand.
Could you please post the file so I can look at it better?

@rmyorston
Copy link
Owner

I can't think of anything better than what you're doing: running the batch file and listing the resulting environment in a format suitable for import to the shell.

One minor improvement would be to run cmd.exe in a reduced environment (as far as possible, see #426) so we (mostly) just need to process newly set variables. This appears to do the trick:

env -i COMSPEC="$COMSPEC" PATH="$PATH" cmd /c ...

I'm also not sure about the sed '1,5d': in my testing it was necessary to remove fewer lines. But that might just be because my test didn't reflect what vcvars actually does.

@rmyorston
Copy link
Owner

A different approach:

temp_file1=$(mktemp)
temp_file2=$(mktemp)
temp_file3=$(mktemp)

cmd /c 'vcvars.bat >nul & busybox sh -c export' | sort >"$temp_file1"

export | sort >"$temp_file2"

comm -2 -3 "$temp_file1" "$temp_file2" | grep -v 'SHLVL=' >"$temp_file3"

. "$temp_file3"

export CC=cl
export CXX=cl

rm "$temp_file1" "$temp_file2" "$temp_file3"

Instead of using set from cmd.exe to get the new environment use the shell's export built-in. This produces output in a form that can be sourced.

Use comm to compare the environment generated by vcvars.bat with the current environment. The result should be a file listing only the variables which have been changed or added by vcvars.bat. Source that.

Add error checking to taste. Use at your own peril.

@doctorpangloss
Copy link
Author

I am observing that both our approaches produce errors when compiling the Python package flash_attn on Windows, whereas my original snippet cmd /c 'C:\PROGRA~2\MICROS~2\2022\BUILDT~1\VC\AUXILI~1\Build\VCVARS~1.BAT amd64 & sh -ilX' does not. I am investigating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants