@echo off
setlocal EnableDelayedExpansion
REM ---------------------------------------------------------------------------
REM     abuild.bat  -  by Don Cross  -  https://cosinekitty.com
REM     Arduino command-line build for Windows.
REM ---------------------------------------------------------------------------

REM     Initialize stuff here...
set abuild_release_date=9 March 2007
set abuild_error=echo.abuild.bat: *** ERROR:
set abuild_report=rem
set abuild_retcode=1
set abuild_output=.\obj
set abuild_rebuild_runtime=false
set abuild_upload=true
set abuild_verbose=false

REM ---------------------------------------------------------------------------
REM     Look for command line options...
:NextOption
if /i "%1" == "-v" (
    set abuild_report=echo.abuild.bat:
    set abuild_verbose=true
    shift
    goto NextOption
)

if /i "%1" == "-o" (
    if "%2" == "" (
        !abuild_error! expected output path after '-o'
        goto end
    )
    set abuild_output=%2
    shift
    shift
    goto NextOption
)

if /i "%1" == "-r" (
    set abuild_rebuild_runtime=true
    shift
    goto NextOption
)

if /i "%1" == "-c" (
    set abuild_upload=false
)

if "%1" == "" (goto usage)

REM ---------------------------------------------------------------------------
REM     Check for ARDUINO_PATH environment variable
if not defined arduino_path (
    !abuild_error! Must define environment variable ARDUINO_PATH to point to Arduino installation.
    goto end
)

REM ---------------------------------------------------------------------------
REM     Verify that ARDUINO_PATH points to a valid Arduino-0007 installation...

set arduino_runtime=!arduino_path!\lib\targets\arduino
for %%f in (
    "!arduino_path!\cygwin1.dll"
) do (
    if not exist %%f (
        !abuild_error! The ARDUINO_PATH environment variable does not point to a valid Arduino installation.
        !abuild_error! Expected file [%%f] was missing
        goto end
    )
)


REM ---------------------------------------------------------------------------
REM     Make sure we can find cygwin1.dll and compiler/linker tools...
set path=!arduino_path!;!arduino_path!\tools\avr\bin;!path!
!abuild_report! set path to: !path!

set abuild_SketchName=%1
if not exist !abuild_SketchName! (
    !abuild_error! File !abuild_SketchName! does not exist.
    goto end
)

REM ---------------------------------------------------------------------------
REM     Parse the Arduino preferences.txt file and set environment variables accordingly...

call agetpref.bat agetpref_internal
if not !errorlevel! == 0 (
    goto end
)

REM ---------------------------------------------------------------------------

if not exist !abuild_output! (
    md !abuild_output!
    if not exist !abuild_output! (
        !abuild_error! Cannot create output path !abuild_output!
        goto end
    )
)

if /i "!abuild_SketchName:~-4!" == ".pde" (
    REM     If we see .pde on the end, we will do a tiny amount of preprocessing,
    REM     but not as much as the Arduino IDE would do.
    set abuild_cppname=!abuild_output!\!abuild_SketchName!.cpp
    set abuild_preprocess=true
    !abuild_report! found PDE file; will do minor preprocessing ==^>  !abuild_cppname!
    > !abuild_cppname! echo.#include ^<WProgram.h^>
    >>!abuild_cppname! type !abuild_SketchName!
    if exist "!arduino_runtime!\main.cxx" (
        REM     Getting here means we are using the library optimization patch.
        >>!abuild_cppname! type "!arduino_runtime!\main.cxx"
    )
) else (
    !abuild_report! found non-PDE file; will not preprocess.
    set abuild_cppname=!abuild_SketchName!
    set abuild_preprocess=false
)

!abuild_report! Compiler output will go to:  !abuild_output!

REM ---------------------------------------------------------------------------
REM     Clean up any stale output from the previous build...

for %%f in (
    !abuild_output!\*.elf
    !abuild_output!\*.hex 
    !abuild_output!\*.rom
) do (
    !abuild_report! deleting old %%f
    del %%f
    if exist %%f (
        !abuild_error! Cannot delete %%f
        goto end
    )
) 

REM ---------------------------------------------------------------------------
REM     Compile the user's sketch first, to help him find errors quicker...

set abuild_gcc_opts=-c -g -Os "-I!arduino_runtime!" -w -mmcu=!pref_build.mcu! -DF_CPU=!pref_build.f_cpu! -DABUILD_BATCH=1
set abuild_gpp_opts=!abuild_gcc_opts! -fno-exceptions
set abuild_short_name=

for %%f in (!abuild_cppname!) do (
    set abuild_short_name=%%~nf
    set abuild_user_objfile=!abuild_output!\%%~nf.cpp.o
    set abuild_cmd=avr-g++ !abuild_gpp_opts! %%f -o!abuild_user_objfile!
    !abuild_report! !abuild_cmd!
    if exist !abuild_user_objfile! (del !abuild_user_objfile!)
    !abuild_cmd!
    if not exist !abuild_user_objfile! (
        !abuild_error! cannot compile %%f
        goto end
    )
)

if not defined abuild_short_name (
    !abuild_error! Problem finding short name for !abuild_cppname!
    goto end
)

REM ---------------------------------------------------------------------------
REM     Compile all the C/C++ code for the runtime library...
REM     Note that we encode the microcontroller name in the runtime library
REM     name, so if the user switches microcontrollers, we build a new one.

set abuild_runtime_shortname=arduino_runtime_!pref_build.mcu!.a
set abuild_runtime_library=!abuild_output!\!abuild_runtime_shortname!
if !abuild_rebuild_runtime! == false (
    if exist !abuild_runtime_library! (
        !abuild_report! Runtime library already exists
        goto link_phase
    ) else (
        !abuild_report! Runtime library does not exist; building it now
    )
) else (
    !abuild_report! Forcing rebuild of runtime library because of -r option
)

if exist !abuild_runtime_library! (
    del !abuild_runtime_library!
)

for %%f in ("!arduino_runtime!\*.c") do (
    set abuild_objfile=!abuild_output!\%%~nf.c.o
    set abuild_cmd=avr-gcc !abuild_gcc_opts! "%%~f" "-o!abuild_objfile!"
    !abuild_report! !abuild_cmd!
    if exist !abuild_objfile! (del !abuild_objfile!)
    !abuild_cmd!
    if not exist !abuild_objfile! (goto end)
    if not !errorlevel! == 0 (goto end)
    
    set abuild_cmd=avr-ar rcs !abuild_runtime_library! !abuild_objfile!
    !abuild_report! !abuild_cmd!
    !abuild_cmd!
    if not !errorlevel! == 0 (goto end)
)

for %%f in ("!arduino_runtime!\*.cpp") do (
    set abuild_objfile=!abuild_output!\%%~nf.cpp.o
    set abuild_cmd=avr-g++ !abuild_gpp_opts! "%%~f" "-o!abuild_objfile!"
    !abuild_report! !abuild_cmd!
    if exist !abuild_objfile! (del !abuild_objfile!)
    !abuild_cmd!
    if not exist !abuild_objfile! (goto end)
    if not !errorlevel! == 0 (goto end)
    
    set abuild_cmd=avr-ar rcs !abuild_runtime_library! !abuild_objfile!
    !abuild_report! !abuild_cmd!
    !abuild_cmd!
    if not !errorlevel! == 0 (goto end)
)

REM ---------------------------------------------------------------------------
REM     Link everything...

:link_phase

REM     Link to an ELF file...
set abuild_elf=!abuild_output!\!abuild_short_name!.elf
set abuild_cmd=avr-gcc -Os "-Wl,-u,vfprintf -lprintf_flt -lm,-Map=!abuild_output!\!abuild_short_name!.map,--cref" -mmcu=!pref_build.mcu! -o !abuild_elf! !abuild_user_objfile! !abuild_runtime_library! -L!abuild_output!
!abuild_report! !abuild_cmd!
!abuild_cmd!
if not exist !abuild_elf! (goto end)

REM     Convert ELF to ROM...

set abuild_rom=!abuild_output!\!abuild_short_name!.rom
set abuild_cmd=avr-objcopy -O srec -R .eeprom !abuild_elf! !abuild_rom!
!abuild_report! !abuild_cmd!
!abuild_cmd!
if not exist !abuild_rom! (goto end)
echo.rbuild.bat: Successfully built !abuild_rom!

REM     Convert ELF to HEX...

set abuild_hex=!abuild_output!\!abuild_short_name!.hex
set abuild_cmd=avr-objcopy -O ihex -R .flash !abuild_elf! !abuild_hex!
!abuild_report! !abuild_cmd!
!abuild_cmd!
if not exist !abuild_hex! (goto end)
echo.rbuild.bat: Successfully built !abuild_hex!

REM     Display binary size...
avr-size !abuild_hex!

REM ---------------------------------------------------------------------------

if not !abuild_upload! == true (
    goto success
)

:get_choice
echo.
echo.[Remember to reset your board right before uploading.]
echo.Enter the first character of your choice...
set abuild_choice=
set /p abuild_choice=Upload, Quit? 

if /i "!abuild_choice!" == "q" (
    goto success
)

if /i "!abuild_choice!" == "u" (
    call aupload.bat !abuild_hex!
    if not !errorlevel! == 0 (goto get_choice)
    goto success
)

echo.*** Invalid choice ***
goto get_choice


REM ---------------------------------------------------------------------------
REM     Getting here means everything completed successfully...
:success
set abuild_retcode=0
goto end

REM ---------------------------------------------------------------------------

:usage
echo.
echo.abuild.bat  -  Arduino command-line build for Windows.
echo.
echo.Usage:
echo.
echo.    abuild [options] sketchname
echo.
echo.where sketchname is the name of your sketch, 
echo.e.g. MySketch.cpp or MySketch.pde.
echo.This batch file will do minor preprocessing to sketches
echo.ending with .pde, such as including WProgram.h and inserting
echo.main() code for you.  You may need to modify sketches developed
echo.in the Arduino IDE a little bit to have their own function
echo.prototypes, etc.  Sketches with other extensions will be 
echo.compiled as-is using the C++ compiler.
echo.
echo.Options:
echo.
echo.    -c        Compile only; do not upload
echo.    -r        Force rebuild of runtime library
echo.    -o dir    Sets compiler output path to dir.  default = .\obj
echo.    -v        Display verbose messages
echo.
echo.This batch file was released on !abuild_release_date!.
echo.Check the following web page for the latest version:
echo.
echo.    https://playground.arduino.cc/Code/WindowsCommandLine
echo.
goto end

REM ---------------------------------------------------------------------------

:end
!abuild_report! exiting with return value !abuild_retcode!
exit /b !abuild_retcode!

REM ---------------------------------------------------------------------------
REM     $Log: abuild.bat,v $
REM     Revision 1.12  2007/03/09 23:07:24  dcross
REM     Oops!  Forgot to update the release date.  Now made it easier to do in the future.
REM
REM     Revision 1.11  2007/03/09 22:58:17  dcross
REM     Arduino forum member "brunob" found a bug where ARDUINO_PATH contains spaces.
REM     Fixed this batch file to work in that case.
REM
REM     Revision 1.10  2007/01/07 23:43:01  dcross
REM     Oops!  Forgot about the fact that I am testing with my library patch, not original distribution.
REM     Now fixed to work with both.
REM
REM     Revision 1.9  2007/01/07 22:53:53  dcross
REM     Usage text now displays link to where to get latest version on Arduino Playground.
REM     Also displays its own release date so user can tell whether what he has is up-to-date.
REM
REM     Revision 1.8  2007/01/07 22:31:08  dcross
REM     Now call agetpref.bat to get Arduino preferences, instead of having hardcoded options.
REM
REM     Revision 1.7  2007/01/07 21:40:55  dcross
REM     Improved upload step by allowing user to either Upload or Quit.
REM     If upload is selected, and fails, we loop back and allow user to try again.
REM
REM     Revision 1.6  2007/01/06 23:15:50  dcross
REM     Now prompt to upload the sketch after compiling and linking successfully,
REM     unless -c is specified on the command line.
REM
REM     Revision 1.5  2007/01/06 22:23:20  dcross
REM     Now define C/C++ preprocessor symbol ABUILD_BATCH so that sketches can easily be made
REM     to work in both the IDE and in the command line.
REM
REM     Revision 1.4  2007/01/06 21:35:29  dcross
REM     Now call avr-size to display binary size.
REM
REM     Revision 1.3  2007/01/06 21:31:37  dcross
REM     Discovered that if you run the IDE after running abuild.bat, the presence of an extra .cpp file
REM     confuses the IDE into thinking you have added a new module, causing both files to be compiled
REM     and linked... resulting in lots of linker errors!  Now generate preprocessed .cpp file in the obj subdirectory.
REM
REM     Revision 1.2  2007/01/06 17:22:51  dcross
REM     Good news!  It looks like we will be able to get rid of the icky link_order file.
REM     It turns out that we can put all the .o object files into a single .a library file, in
REM     which case the order appears to be irrelevant.
REM     Still need to port this over to the IDE java code.
REM
REM     Revision 1.1  2007/01/05 22:34:27  dcross
REM     First version... seems to work for building ROM and HEX files, but I don't yet know how to
REM     upload and test them on a real microcontroller board.
REM