--- title: "Build Files" draft: false description: "Understanding AdvMake Build Files" --- {{< button-gitea color="green" project="advmake" text="AdvMake" >}} {{< button-gitlab color="OrangeRed" project="advmake" text="AdvMake" >}} ### Format AdvMake uses [Starlark](https://github.com/bazelbuild/starlark) as the format for its build files. Extra builtins are also defined for both convenience and extra functionality. Starlark is a Python-like language meant for configuration files. ### Configuration Build files are by default called `AdvMakefile`, but that can be set via `-f` An AdvMakefile example can be found at AdvMake's repo as it uses AdvMake itself. AdvMake runs functions exposed by starlark in the format `_`. To set the default name and target, the global variables `defaultName`, and `defaultTarget` must be set. Here is an example from AdvMake's AdvMakefile: ```python defaultName = "advmake" defaultTarget = "build" ``` This will tell AdvMake to run the function `advmake_build()` when run with no arguments. If AdvMake is run with one argument (such as `advmake install`), it will use the default name with the specified target, so in that case, it would run `advmake_install()`. If run with two arguments, AdvMake will use the first argument as the name and the second as the target. So, running `advmake hello world` would run the function `hello_world()`. ### Builtins As previously mentioned, AdvMake comes with extra builtins. Those are as follows: #### `log()` The log function uses zerolog in go to log a message to STDOUT. It has two arguments. The first is a string with the message to log, and the second is `level` which is optional Examples: ```python log("Info log") # Default level is info log("Warn log", level="warn") # Warn level log log("Debug log", level="debug") # Debug level log log("Fatal log", level="fatal") # Fatal level log. This will exit the program when executed ``` --- #### `execute()` The execute function runs a script using `sh -c`. This function has three arguments. The first is required and is a string with the script to run, the second is `output` which is optional. It can be set to `return`, `stdout`, or `both`, and the default is `both`. The `output` argument controls where the script's output will be directed: - `return`: Returns script output as string - `stdout`: Prints script output to STDOUT, returning nothing - `both`: Prints to STDOUT and returns as string The third argument is `concurrent` which can be either `True` or `False`, default `False`. If `concurrent` is set to `True`, all the lines in the script will be split and run concurrently via goroutines. The maximum threads for goroutines can be controlled using the `GOMAXPROCS` environment variable and is by default the amount of CPU cores present. Examples: ```python user = execute("whoami") # This will print the username to STDOUT and set the user variable to it user = execute("whoami", output="return") # This will set the user variable to the username but not print it execute(""" cp file destination mv destination destination-1 echo 'hello world' """) # Example of a multiline script execute(""" install -Dm755 program /usr/bin install -Dm755 program.cfg /etc """, concurrent=True) # Example of a concurrent multiline script ``` --- #### `getEnv()` The getEnv function simply returns the value of the environment variable specified in its first argument. Example: ```python term = getEnv("TERM") # Sets variable term to value of $TERM print("Nice " + term) # Prints "Nice $TERM" ``` --- #### `setEnv()` The setEnv function sets an environment variable. It has three arguments. The first is the key, it is the name of the environment variable. The second is the new value, what the key should be set to. The third is optional, it is `onlyIfUnset` and it can be set to `True` or `False`, default `False` `onlyIfUnset` checks that the variable is not already set before setting it, this can be useful for setting defaults. Examples: ```python setEnv("MY_ENV_VAR", "Hello, World") # Sets $MY_ENV_VAR to "Hello, World" setEnv("CC", "gcc", onlyIfUnset=True) # Sets $CC to "gcc", but only if $CC is not already set ``` --- #### `expandFile()` The expandFile function replaces all instances of $VAR with the value specified. expandFile has two arguments. The first accepts a filename to modify. The second accepts a dictionary to act as mappings for value replacements. Example: ```python expandFile("a.txt", {"A": "Hello", "B": "World"}) # Replace $A with Hello and $B with world in file a.txt ``` --- #### `download()` The download function downloads a file at a URL. download has two arguments. The first is a URL, and the second is an optional argument called `filename`. If `filename` is not provided, the filename will be taken from the URL. Examples: ```python download("https://www.arsenm.dev/logo-white.png") # Downloads logo-white.png download("https://www.arsenm.dev/logo-white.png", filename="logo.png") # Downloads logo-white.png as logo.png ``` --- #### `lookPath()` The lookPath function uses go's `exec.LookPath()` to find the absolute path of a command. It has a single argument which is the command to look for. If a command is not found, lookPath returns `-1`. Examples: ```python lookPath("sh") # /bin/sh lookPath("nonExistentCommand") # -1 ``` --- #### `userChoice()` The userChoice function presents the user with a choice. It has two arguments. The first is a prompt to be displayed to the user, and the second is a list of choices. Example: ```python userChoice("Choose command", ["find", "ls"]) # This returns: # [1] "find" # [2] "ls" # Choose command: ``` The function will return the chosen object (if input to above is `1`, function returns `"find"`) --- #### `input()` The input function is a simple function that uses go's `fmt.Print()` and `fmt.Scanln()` to replicate the functionality of python's `input()` function. It has a single argument, which is the prompt and returns the inputted text. Example: ```python x = input("Name: ") # This will print "Name: " and then wait for input. ``` --- #### `fileExists()` The fileExists function checks if a specified file exists and is accessible in the filesystem. It has a single argument which is the path to the file being checked, and returns a boolean reflecting the state of the file. Examples: ```python if fileExists("/etc/passwd"): print("/etc/passwd exists!") # /etc/passwd exists! if fileExists("/abcdef"): print("/abcdef exists!") # No output because /abcdef most likely does not exist ``` --- #### `getOS()` The getOS function returns the value of `runtime.GOOS`. It has no arguments. Example: ```python if getOS() == "linux": print("This is Linux!") ``` --- #### `getArch()` The getArch function returns the value of `runtime.GOARCH`. It has no arguments. Example: ```python if getArch() == "386": print("x86 32-bit") ``` --- #### `getCPUNum()` The getCPUNum function returns the amount of CPUs available to AdvMake. It has no arguments. Example: ```python print(getCPUNum() + " CPUs available!") ``` ---