Repository: pyinstaller/pyinstaller

Issue:
PyInstaller 5.0.1 can't find icon
## Description of the issue
PyInstaller fails to find an icon specified with a valid path,s eems to be caused by the path being joined with specpath here 
https://github.com/pyinstaller/pyinstaller/blob/1a7d704ffbabb433007e3ba04750c2f13ade48e5/PyInstaller/utils/win32/icon.py#L95-L106

the SystemExit logs `path` which is a valid path (`.\pyinstaller_build\../icon/icons_library.ico` in the linked example), but `self.path` is used for the file which joins specpath with the passed in path again (`.\pyinstaller_build\.\pyinstaller_build\../icon/icons_library.ico`)
### Context information (for bug reports)

* Output of `pyinstaller --version`: `5.0.1`
* Version of Python: 3.10.4
* Platform: Windows
* How you installed Python: python.org/downloads
* Did you also try this on another platform? Does it work there?

### A minimal example program which shows the error
https://github.com/Numerlor/pyinstaller_icon
set up project (install pyinstaller/poetry install) and run `pyinstaller .\pyinstaller_build\file.spec` from the project root


Discussion:
These lines should probably be removed: https://github.com/pyinstaller/pyinstaller/blob/85d04eedbf4cf56006863ea8ad88363f69c89fee/PyInstaller/utils/win32/icon.py#L98-L99
Similarly as to how #6775 removed the other `os.path.isabs()` check in this file.

---

Although the root of the problem is that `CONF['spec']` and `CONF['specpath']` are not resolved to full absolute path, but are rather left in their original relative form. So prepending it to the icon path does not produce an absolute path, hence it ends up being prepended twice in two different places. Similarly, it seems that `CONF['distpath']` and `CONF['workpath']` are also not resolved if relative paths are provided via `--distpath` and `--workpath` CLI switches...
FWIW I still do see issues in my project as well, which worked fine with PyInstaller 4.9.

With 5.0.1, I see:

```
41170 INFO: Copying icons from ['misc\\..\\qutebrowser\\icons\\qutebrowser.ico']
Unable to open icon file misc\..\qutebrowser\icons\qutebrowser.ico
```

but it's there:

```
PS C:\Users\florian.bruhin\proj\qutebrowser> ls .\misc\qutebrowser.spec


    Directory: C:\Users\florian.bruhin\proj\qutebrowser\misc


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----          5/2/2022   9:35 AM           2503 qutebrowser.spec


PS C:\Users\florian.bruhin\proj\qutebrowser> ls .\misc\..\qutebrowser\icons\qutebrowser.ico


    Directory: C:\Users\florian.bruhin\proj\qutebrowser\qutebrowser\icons


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----          4/5/2022  12:20 PM         115490 qutebrowser.ico
```

Resolving patch:
diff --git a/PyInstaller/building/build_main.py b/PyInstaller/building/build_main.py
--- a/PyInstaller/building/build_main.py
+++ b/PyInstaller/building/build_main.py
@@ -685,11 +685,11 @@ def build(spec, distpath, workpath, clean_build):
 
     # Ensure starting tilde and environment variables get expanded in distpath / workpath.
     # '~/path/abc', '${env_var_name}/path/abc/def'
-    distpath = compat.expand_path(distpath)
-    workpath = compat.expand_path(workpath)
-    CONF['spec'] = compat.expand_path(spec)
+    distpath = os.path.abspath(compat.expand_path(distpath))
+    workpath = os.path.abspath(compat.expand_path(workpath))
+    CONF['spec'] = os.path.abspath(compat.expand_path(spec))
 
-    CONF['specpath'], CONF['specnm'] = os.path.split(spec)
+    CONF['specpath'], CONF['specnm'] = os.path.split(CONF['spec'])
     CONF['specnm'] = os.path.splitext(CONF['specnm'])[0]
 
     # Add 'specname' to workpath and distpath if they point to PyInstaller homepath.
@@ -700,6 +700,7 @@ def build(spec, distpath, workpath, clean_build):
         workpath = os.path.join(HOMEPATH, CONF['specnm'], os.path.basename(workpath), CONF['specnm'])
     else:
         workpath = os.path.join(workpath, CONF['specnm'])
+    CONF['workpath'] = workpath
 
     CONF['warnfile'] = os.path.join(workpath, 'warn-%s.txt' % CONF['specnm'])
     CONF['dot-file'] = os.path.join(workpath, 'graph-%s.dot' % CONF['specnm'])
@@ -719,7 +720,7 @@ def build(spec, distpath, workpath, clean_build):
                         os.remove(f)
 
     # Create DISTPATH and workpath if they does not exist.
-    for pth in (CONF['distpath'], workpath):
+    for pth in (CONF['distpath'], CONF['workpath']):
         os.makedirs(pth, exist_ok=True)
 
     # Construct NAMESPACE for running the Python code from .SPEC file.
@@ -737,7 +738,7 @@ def build(spec, distpath, workpath, clean_build):
         'specnm': CONF['specnm'],
         'SPECPATH': CONF['specpath'],
         'WARNFILE': CONF['warnfile'],
-        'workpath': workpath,
+        'workpath': CONF['workpath'],
         # PyInstaller classes for .spec.
         'TOC': TOC,
         'Analysis': Analysis,
@@ -753,17 +754,13 @@ def build(spec, distpath, workpath, clean_build):
         'pyi_crypto': pyz_crypto,
     }
 
-    # Set up module PyInstaller.config for passing some arguments to 'exec' function.
-    from PyInstaller.config import CONF
-    CONF['workpath'] = workpath
-
     # Execute the specfile. Read it as a binary file...
     try:
         with open(spec, 'rb') as f:
             # ... then let Python determine the encoding, since ``compile`` accepts byte strings.
             code = compile(f.read(), spec, 'exec')
     except FileNotFoundError:
-        raise SystemExit('spec "{}" not found'.format(spec))
+        raise SystemExit(f'Spec file "{spec}" not found!')
     exec(code, spec_namespace)
 
 
diff --git a/PyInstaller/utils/win32/icon.py b/PyInstaller/utils/win32/icon.py
--- a/PyInstaller/utils/win32/icon.py
+++ b/PyInstaller/utils/win32/icon.py
@@ -95,15 +95,13 @@ class GRPICONDIRENTRY(Structure):
 class IconFile:
     def __init__(self, path):
         self.path = path
-        if not os.path.isabs(path):
-            self.path = os.path.join(config.CONF['specpath'], path)
         try:
             # The path is from the user parameter, don't trust it.
             file = open(self.path, "rb")
         except OSError:
             # The icon file can't be opened for some reason. Stop the
             # program with an informative message.
-            raise SystemExit('Unable to open icon file {}'.format(path))
+            raise SystemExit(f'Unable to open icon file {self.path}!')
         with file:
             self.entries = []
             self.images = []


Test patch: